{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# STFT Analysis/Synthesis - MusicBricks Tutorial"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial will guide you through some tools for performing spectral analysis and synthesis using the Essentia library (http://www.essentia.upf.edu). STFT stands for Short-Time Fourier Transform and it processes an input audio signal as a sequence of spectral frames. Spectral frames are complex-valued arrays contain the frequency representation of the windowed input signal.\n",
    "\n",
    "This algorithm shows how to analyze the input signal, and resynthesize it again, allowing to apply new transformations directly on the spectral domain."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should first install the Essentia library with Python bindings. Installation instructions are detailed here: http://essentia.upf.edu/documentation/installing.html . \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Processing steps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# import essentia in streaming mode\n",
    "import essentia\n",
    "import essentia.streaming as es"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After importing Essentia library, let's import other numerical and plotting tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# import matplotlib for plotting\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define the parameters of the STFT workflow"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# algorithm parameters\n",
    "framesize = 1024\n",
    "hopsize = 256"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Specify input and output audio filenames"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "inputFilename = 'singing-female.wav'\n",
    "outputFilename = 'singing-female-stft.wav'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# create an audio loader and import audio file\n",
    "out = np.array(0)\n",
    "loader = es.MonoLoader(filename = inputFilename, sampleRate = 44100)\n",
    "pool = essentia.Pool()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define algorithm chain for frame-by-frame process: \n",
    "FrameCutter -> Windowing -> FFT -> IFFT -> OverlapAdd -> AudioWriter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# algorithm instantation\n",
    "fcut = es.FrameCutter(frameSize = framesize, hopSize = hopsize, startFromZero =  False);\n",
    "w = es.Windowing(type = \"hann\");\n",
    "fft = es.FFT(size = framesize);\n",
    "ifft = es.IFFT(size = framesize);\n",
    "overl = es.OverlapAdd (frameSize = framesize, hopSize = hopsize, gain = 1./framesize );\n",
    "awrite = es.MonoWriter (filename = outputFilename, sampleRate = 44100);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we set the algorithm network and store the processed audio samples in the output file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "loader.audio >> fcut.signal\n",
    "fcut.frame >> w.frame\n",
    "w.frame >> fft.frame\n",
    "fft.fft >> ifft.fft\n",
    "ifft.frame >> overl.frame\n",
    "overl.signal >> awrite.audio\n",
    "overl.signal >> (pool, 'audio')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally we run the process that will store an output file in a WAV file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "essentia.run(loader)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
